from django.core.mail import send_mail
from rest_framework import serializers

from goods.models import SKU
from .models import User

from django.conf import settings
from .models import Address

from django_redis import get_redis_connection
from .models import User
from celery_tasks.email.tasks import send_verify_url

class RegisterUserSerializer(serializers.ModelSerializer):
    # write_only: 只写属性 只效验不入库,也不需要返回到前段浏览
    password2 = serializers.CharField(min_length=8, max_length=20, label="确认二次输入密码", write_only=True)
    sms_code = serializers.CharField(min_length=6, max_length=6, label="短信验证码", write_only=True)
    allow = serializers.CharField(label="协议", write_only=True)  # 只写
    token = serializers.CharField(label='jwt口令', read_only=True)  # 只读

    class Meta:
        model = User
        fields = ("id", "username", "password", "password2", "mobile", "sms_code", "allow", "token")

        read_only_fields = ["id"]  # 设置id为只读

        extra_kwargs = {
            "password": {
                'min_length': 8,
                'max_length': 20,
                'write_only': True
            }
        }

    # 单字段效验
    def validate_allow(self, value):
        if value != 'true':  # 不等于前段携带的数据  是字符串
            raise serializers.ValidationError("未勾选协议")
        return value

    # 效验多字段,密码,短信
    def validate(self, attrs):
        # 取出手机号,和短信验证码
        sms_code = attrs['sms_code']
        mobile = attrs['mobile']

        # 效验密码
        if attrs["password"] != attrs["password2"]:
            raise serializers.ValidationError("两次密码不相同")

        # 效验短信
        redis_conn = get_redis_connection("code")
        redis_sms_code = redis_conn.get("sms_code_%s" % mobile)

        # 判断短信是否过有效期
        if not redis_sms_code:
            raise serializers.ValidationError("短信验证码已过期")

        # 效验正确性
        if sms_code != redis_sms_code.decode():  # 解码
            raise serializers.ValidationError("短信验证码错误")

        # 返回
        return attrs

    # User中没有password2, sms_code, allow属性字段,所以要过滤去除
    def create(self, validated_data):
        # 取出不需要的数据
        del validated_data["password2"]
        del validated_data["sms_code"]
        del validated_data["allow"]
        # 创建序列化器对象
        user = super(RegisterUserSerializer, self).create(validated_data)  # super 直接调用父类的方法
        # 密码加密
        user.set_password(validated_data["password"])  # 使用set_password方法直接加密
        user.save()

        # JWT
        from rest_framework_jwt.settings import api_settings
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER  # 载荷
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER  # 编码对象

        payload = jwt_payload_handler(user)  # 对用户对象进行编码  使用base64
        # 在载荷里获得用户信息
        token = jwt_encode_handler(payload)  # 对载荷进行编码
        user.token = token  # 给用户添加一个token属性

        # 返回
        return user

"""用户中心的序列化器"""
class UserInfoSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ("id", "username", "mobile", "email", "email_active")

class EmailSendSerializer(serializers.Serializer):
    email = serializers.EmailField(label="邮箱")   # 与模型类字段名字保持一致

    # 实现update方法
    def update(self, instance, validated_data):
        # 将邮箱设置到用户对象
        email = validated_data["email"]
        instance.email = email  # 接收的邮箱
        instance.save()
        # 发送邮箱,发送邮件
        verify_url = instance.generate_verify_url()

        # send_mail(subject="点击链接验证",
        #           message=verify_url,
        #           from_email=settings.EMAIL_FROM,  # 收件人看到的发件人
        #           recipient_list=[email])

        # 使用cekery_tasks里重写的send_verify_url方法发送邮件
        send_verify_url.delay(verify_url, email)

        # 返回
        return validated_data


"""地址序列化器"""
class AddressSerializer(serializers.ModelSerializer):
    province = serializers.StringRelatedField(read_only=True)  # 显示数据而不是外键ID
    city = serializers.StringRelatedField(read_only=True)
    district = serializers.StringRelatedField(read_only=True)
    province_id = serializers.IntegerField(label="省ID")
    city_id = serializers.IntegerField(label="市ID")
    district_id = serializers.IntegerField(label="区ID")

    class Meta:
        model = Address
        exclude = ("user", "is_deleted", "create_time", "update_time")

    # 重写序列化器的create方法 可以给create的数据补充一个user
    def create(self, validated_data):
        validated_data["user"] = self.context["request"].user
        return super(AddressSerializer, self).create(validated_data)

"""修改地址序列化器"""
class AddressTitleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Address
        fields = ("title", )

"""商品浏览记录序列化器"""
class UserBrowerHistorySerializer(serializers.Serializer):
    sku_id = serializers.IntegerField(min_value=1, label="商品编号")

    # 单子段效验
    def validate_sku_id(self, value):
        # 通过sku_id获取sku对象
        try:
            sku = SKU.objects.get(id=value)
        except Exception as e:
            raise serializers.ValidationError("商品不存在")

        # 返回 sku_id
        return value

    # 重写create方法, 需要保存记录到redis中
    def create(self, validated_data):
        # 获取sku_id
        sku_id = validated_data.get("sku_id")
        user = self.context["request"].user
        # 获取redis 对象
        redis_conn = get_redis_connection("history")  # 获取redis库
        # 去重/ 删除浏览的记录
        redis_conn.lrem("history_%s" % user.id, 0, sku_id)
        # 存储 存储一个新的sku
        redis_conn.lpush("history_%s" % user.id, sku_id)
        # 截取五条
        redis_conn.ltrim("history_%s" % user.id, 0, 4)

        # 返回
        return validated_data

class UPpasswordSerializer(serializers.ModelSerializer):
    nwe_password1 = serializers.CharField(min_length=8, max_length=128, label="新密码")
    nwe_password2 = serializers.CharField(min_length=8, max_length=128, label="重复密码")

    class Meta:
        model = User

        fields = ["old_password", "nwe_password1", "new_password2"]

    def validate(self, attrs):
        """多字段校验"""
        user = self.context["request"].user
